/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is ThumbsDown.
 *
 * The Initial Developer of the Original Code is Atte Kemppilä.
 * Portions created by the Initial Developer are Copyright (C) 2012
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */


function TargetPage() // extend WizardPage
{
    let depends = "selected linkUrls";
    WizardPage.call(this, depends);
}

TargetPage.prototype =
{
    get targetCount()
    {
        if (! this._targetCount)
        {
            let count = {image: 0, page: 0, unknown: 0, error: 0, loading: 0};
            
            for each (let entry in this.entries)
                if (entry.target && entry.target.result)
                    count[entry.target.result]++;
            
            this._targetCount = count;
        }
        return this._targetCount;
    },
    
    onPageShow: function()
    {
        if (this.firstRun)
        {
            this.$tree = document.getElementById("tree_target");
            this.$treeChildren = document.getElementById("treechildren_target");
            this.$thumbnail = document.getElementById("image_target_thumbnail");
            this.$thumbnailBox = document.getElementById("box_target_thumbnail");
            this.$thumbnailSize = document.getElementById("lbl_target_thumbnailSize");
            
            let self = this;
            this.$treeChildren.addEventListener("DOMMouseScroll", function(e) { self.onThumbnailTreeMouseMove(e); }, false);
            this.$thumbnail.addEventListener("load", function() { self.onThumbnailLoad(); }, false);
        }
        
        if (this.dirty.page)
        {
            this.entries = [];
            this._targetCount = null;
            
            for (let i = 0; i < model.selected.length; i++)
                this.entries.push({thumbnail: model.selected[i], linkUrl: model.linkUrls[i]});
            
            this.$tree.view = this.treeView = new TargetTreeView(this.entries);
            
            this._getTargetHead(this.entries);
        }
        
        this._setThumbnail(null);
    },
    
    _getTargetHead: function(entries)
    {
        let timeout = ThumbsDown.prefs.getIntPref("scriptwizard.requestTimeout") * 1000;
        
        for each (let entry in entries)
        {
            let target = entry.target = {};
            
            let self = this;
            let callback = function(loader)
            {
                if (loader.success)
                {
                    target.result = "unknown";
                    target.status = loader.request.status;
                    target.contentType = loader.request.getResponseHeader("Content-Type");
                    if (target.contentType)
                    {
                        let match =  /^([-\w]+\/[-\w]+)/.exec(target.contentType);
                        if (match)
                        {
                            target.mimeType = match[1];
                            if (/^image\/\w+/.test(target.mimeType))
                                target.result = "image";
                            else if (target.mimeType == "text/html")
                                target.result = "page";
                        }
                    }
                }
                else
                {
                    target.result = (loader.timeout ? "timeout" : "error");
                    if (! loader.timeout)
                        target.status = loader.request.status;
                }
                
                self.onTargetHeadLoad();
            };
            
            target.result = "loading";
            target.loader = new HeadLoader(entry.linkUrl, model.referer, timeout, callback);
        }
    },
    
    onTargetHeadLoad: function()
    {
        this._targetCount = null;
        
        if (page != pages["target"])
            return;
        
        this.$tree.treeBoxObject.invalidate();
        
        wizard.updateWizardButtons();
    },
    
    onThumbnailTreeKeyUp: function()
    {
        let row = this.$tree.currentIndex;
        this._setThumbnail((row >= 0) ? this.entries[row].thumbnail : null);
    },
    
    onThumbnailTreeMouseMove: function(e)
    {
        let row = {}, col = {};
        this.$tree.treeBoxObject.getCellAt(e.clientX, e.clientY, row, col, {});
        [row, col] = [row.value, col.value];
        
        this._setThumbnail((row >= 0) ? this.entries[row].thumbnail : null);
        
        if (row >= 0)
            this._updateTreeTooltip(this.treeView.getTooltipText(row, col));
    },
    
    onThumbnailTreeMouseOut: function(e)
    {
        this._setThumbnail(null);
    },
    
    onThumbnailLoad: function()
    {
        if (page != pages["target"])
            return;
        
        this._updateThumbnailSize();
    },
    
    _setThumbnail: function(thumbnail)
    {
        if (thumbnail === this.thumbnail)
            return;
        
        this.thumbnail = thumbnail;
        
        if (this.thumbnail)
        {
            let boxComputedStyle = document.defaultView.getComputedStyle(this.$thumbnailBox, null);
            let boxWidth = boxComputedStyle.width.replace(/px$/, "");
            let boxHeight = boxComputedStyle.height.replace(/px$/, "");
            
            this.$thumbnail.src = this.thumbnail.thumbnailUrl;
            this.$thumbnail.setSize(boxWidth, boxHeight);
        }
        else
        {
            this.$thumbnail.src = "";
            this._updateThumbnailSize();
        }
    },
    
    _updateTreeTooltip: function(text)
    {
        this.$treeChildren.setAttribute("tooltiptext", text);
    },
    
    _updateThumbnailSize: function()
    {
        let image = this.thumbnail && this.thumbnail.thumbnailImage;
        
        if (image)
            this.$thumbnailSize.value = image.width + "x" + image.height;
        
        this.$thumbnailSize.parentNode.style.visibility = (image ? "visible" : "hidden");
    },
    
    canAdvance: function()
    {
        // all thumbnails' target must be either image or page
        return (
            (this.targetCount.image == this.entries.length) ||
            (this.targetCount.page == this.entries.length));
    },
    
    onPageAdvanced: function()
    {
        model.target = ((this.targetCount.image > 0) ? "image" : "page");
        
        switch (model.target)
        {
            case "image":
                model.images = [{src: linkUrl} for each (linkUrl in model.linkUrls)];
                return wizard.advance("mode");
            case "page":
                return wizard.advance("images");
            default:
                throw new Error("unknown target: " + model.target);
        }
    }
}

extend(TargetPage, WizardPage);

pages["target"] = new TargetPage();


function TargetTreeView(entries) // extend TreeView
{
    TreeView.call(this, entries);
}

TargetTreeView.prototype =
{
    getCellText: function(row, col)
    {
        let entry = this.model[row];
        
        switch (col.id)
        {
            case "tcol_target_thumbnail":
                return entry.thumbnail.thumbnailUrl;
            
            case "tcol_target_link":
                return entry.linkUrl;
            
            case "tcol_target_target":
                let result = entry.target && entry.target.result;
                switch (result)
                {
                    case "loading": return _("target.loading");
                    case "image":   return _("target.image");
                    case "page":    return _("target.page");
                    case "unknown": return (target.contentType ? _("target.unknown", (target.mimeType ? target.mimeType : target.contentType)) : _("target.noContentType"));
                    case "error":   return _("target.error", (target.status ? target.status : -1));
                    case "timeout": return _("target.timeout");
                    default:        return "";
                }
            
            default: return "";
        }
    },
    
    getCellProperties: function(row, col)
    {
        let props = [];
        let entry = this.model[row];
        
        let result = entry.target && entry.target.result;
        if (! ((result == "image") || (result == "page")))
            props.push("disabled");
        
        if (col.id == "tcol_target_thumbnail")
            props.push("thumbnail_" + entry.thumbnail.type);
        
        return props.join(" ");
    },
    
    getTooltipText: function(row, col)
    {
        switch (col.id)
        {
            case "tcol_target_type":
                return _("thumbnailTypeTooltip", _("thumbnailType." + this.model[row].thumbnail.type));
            default:
                return null;
        }
    }
}

extend(TargetTreeView, TreeView);
